package cn.itguy.mobileguard;

import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.os.Vibrator;
import android.widget.Toast;

public class GuardDetector implements SensorEventListener {

	public static final int MOTION_ALARM_CRITICAL_LEVEL_HIGH = 10;
	public static final int MOTION_ALARM_CRITICAL_LEVEL_LOW = 15;
	public static final int MOTION_ALARM_CRITICAL_LEVEL_MIDDLE = 12;
	
	private int level = MOTION_ALARM_CRITICAL_LEVEL_HIGH;

	private Context context;
	
	private IMGPreferences preferences;
	
	private SensorManager sensorManager;
	private Sensor sensor;

	private AudioManager audioManager;
	private MediaPlayer mediaPlayer;
	
	private Vibrator vibrator;

	private boolean isAlarmOn = false;
	
	private DetectorEventListener detectorEventListener;

	public GuardDetector(Context context) {
		this.context = context;
		preferences = IMGPreferences.getInstance(context);
		
		switch (preferences.getSensorSensitivity()) {
		case 0:
			level = MOTION_ALARM_CRITICAL_LEVEL_LOW;
			break;
		case 1:
			level = MOTION_ALARM_CRITICAL_LEVEL_MIDDLE;
			break;
		case 2:
			level = MOTION_ALARM_CRITICAL_LEVEL_HIGH;
			break;
		}
		
		sensorManager = (SensorManager) context
				.getSystemService(Context.SENSOR_SERVICE);
		sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);

		audioManager = (AudioManager) context
				.getSystemService(Context.AUDIO_SERVICE);
		
		vibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
	}

	public DetectorEventListener getDetectorEventListener() {
		return detectorEventListener;
	}

	public void setDetectorEventListener(DetectorEventListener detectorEventListener) {
		this.detectorEventListener = detectorEventListener;
	}

	public void registerSensor() {
		sensorManager.registerListener(this, sensor,
				SensorManager.SENSOR_DELAY_FASTEST);
	}

	public void unregisterSensor() {
		sensorManager.unregisterListener(this);
	}
	
	public void shutdown() {
		unregisterSensor();
		
		if (null != mediaPlayer) {
			mediaPlayer.release();
			mediaPlayer = null;
		}
		
		vibrator.cancel();
		vibrator = null;
		
	}

	private void alarm() {
		// turn up the volume to max
		turnUpToMaxVolume();
		int jbResId = R.raw.jb0;
		switch (preferences.getAlarmRingIndex()) {
		case 0:
			jbResId = R.raw.jb0;
			break;
		case 1:
			jbResId = R.raw.jb1;
			break;
		case 2:
			jbResId = R.raw.jb2;
			break;
		}
		mediaPlayer = MediaPlayer.create(context, jbResId);
		if (null != mediaPlayer) {
			mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
			mediaPlayer.setLooping(true);
			mediaPlayer.start();
			if (detectorEventListener != null) {
				detectorEventListener.onAlarmStarted();
			}
		} else {
			Toast.makeText(context, R.string.tipText_media_creation_failed,
					Toast.LENGTH_SHORT).show();
			if (detectorEventListener != null) {
				detectorEventListener.onStartAlarmError();
			}
		}
		
		vibrator.vibrate(new long[]{0l, 1000l, 500l}, 0);
	}

	public void turnUpToMaxVolume() {
		audioManager.setStreamVolume(AudioManager.STREAM_MUSIC,
				audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC), 0);
	}

	@Override
	public void onAccuracyChanged(Sensor sensor, int accuracy) {
	}

	@Override
	public void onSensorChanged(SensorEvent event) {
		synchronized (this) {
			if (!isAlarmOn && (Math.abs(event.values[0]) > level
					|| Math.abs(event.values[1]) > level
					|| Math.abs(event.values[2]) > level)) {
				alarm();
				isAlarmOn = true;
				unregisterSensor();
				
			}
		}
	}
	
	public interface DetectorEventListener {

		void onStartAlarmError();

		void onAlarmStarted();
		
	}

}
